{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a497c9ed",
   "metadata": {},
   "source": [
    "# 多动作多智能体-软件公司\n",
    "\n",
    "目标：实现一个软件公司，它可以对外投资，员工状态，项目进度等。\n",
    "\n",
    "**安装依赖**\n",
    "\n",
    "1.安装metagpt\n",
    "```python\n",
    "pip install metagpt\n",
    "```\n",
    "2.安装 pydantic（如果尚未安装）\n",
    "```python\n",
    "pip install pydantic==2.9.4 #pydantic级别高版本会报错\n",
    "```\n",
    "\n",
    "**插入模块**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8c23fcea",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pydantic import BaseModel, Field\n",
    "from metagpt.actions import BossRequirement\n",
    "from metagpt.config import CONFIG\n",
    "from metagpt.environment import Environment\n",
    "from metagpt.logs import logger\n",
    "from metagpt.roles import Role\n",
    "from metagpt.schema import Message\n",
    "from metagpt.utils.common import NoMoneyException"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1167430",
   "metadata": {},
   "outputs": [],
   "source": [
    "**定义角色**\n",
    "\n",
    "1.创建软件公司基础模型\n",
    "\n",
    "```python\n",
    "class SoftwareCompany(BaseModel):\n",
    "    \"\"\"\n",
    "    Software Company: Possesses a team, SOP (Standard Operating Procedures), and a platform for instant messaging,\n",
    "    dedicated to writing executable code.\n",
    "    \"\"\"\n",
    "    environment: Environment = Field(default_factory=Environment)\n",
    "    investment: float = Field(default=10.0)\n",
    "    idea: str = Field(default=\"\")\n",
    "\n",
    "    class Config:\n",
    "        arbitrary_types_allowed = True\n",
    "```\n",
    "\n",
    "**定义动作**\n",
    "\n",
    "在创建的软件公司模型中我们定义了几个动作，包括：雇用员工，对外投资，检查预算平衡，发起项目。\n",
    "\n",
    "```python\n",
    "#雇佣员工\n",
    "def hire(self, roles: list[Role]):\n",
    "    \"\"\"Hire roles to cooperate\"\"\"\n",
    "    self.environment.add_roles(roles)\n",
    "#对外投资\n",
    "def invest(self, investment: float):\n",
    "    \"\"\"Invest company. raise NoMoneyException when exceed max_budget.\"\"\"\n",
    "     self.investment = investment\n",
    "     CONFIG.max_budget = investment\n",
    "     logger.info(f'Investment: ${investment}.')\n",
    "#检查预算平衡\n",
    "def _check_balance(self):\n",
    "    if CONFIG.total_cost > CONFIG.max_budget:\n",
    "        raise NoMoneyException(CONFIG.total_cost, f'Insufficient funds: {CONFIG.max_budget}')\n",
    "#启动项目\n",
    "def start_project(self, idea):\n",
    "    \"\"\"Start a project from publishing boss requirement.\"\"\"\n",
    "    self.idea = idea\n",
    "    self.environment.publish_message(Message(role=\"BOSS\", content=idea, cause_by=BossRequirement))\n",
    "#保存公司状态\n",
    "def _save(self):\n",
    "    logger.info(self.json())\n",
    "```\n",
    "\n",
    "定义软件公司运作，直至目标周转或者公司破产\n",
    "\n",
    "```python\n",
    "# 软件公司运作\n",
    "async def run(self, n_round=3):\n",
    "    \"\"\"Run company until target round or no money\"\"\"\n",
    "    while n_round > 0:\n",
    "        # self._save()\n",
    "        n_round -= 1\n",
    "        logger.debug(f\"{n_round=}\")\n",
    "        self._check_balance()\n",
    "        await self.environment.run()\n",
    "    return self.environment.history\n",
    "```\n",
    "# 定义员工角色\n",
    "```python\n",
    "# 定义员工角色\n",
    "class Engineer(Role):\n",
    "    def __init__(self, **kwargs):\n",
    "        super().__init__(**kwargs)\n",
    "        self.set_actions([BossRequirement])\n",
    "\n",
    "    async def _act(self) -> Message:\n",
    "        logger.info(f\"{self.name} is working on the project.\")\n",
    "        return Message(content=\"Code implemented successfully.\", role=self.name)\n",
    "```\n",
    "**主函数**\n",
    "```python\n",
    "async def main():\n",
    "    # 初始化软件公司\n",
    "    company = SoftwareCompany()\n",
    "\n",
    "    # 投资公司\n",
    "    company.invest(investment=20.0)\n",
    "\n",
    "    # 雇用员工\n",
    "    engineer1 = Engineer(name=\"Engineer1\")\n",
    "    engineer2 = Engineer(name=\"Engineer2\")\n",
    "    company.hire(roles=[engineer1, engineer2])\n",
    "\n",
    "    # 启动项目\n",
    "    company.start_project(idea=\"Build a new web application.\")\n",
    "\n",
    "    # 运行公司\n",
    "    history = await company.run(n_round=5)\n",
    "    logger.info(\"Company run completed.\")\n",
    "    logger.info(f\"History: {history}\")\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    # 使用 asyncio 运行主函数\n",
    "    asyncio.run(main())\n",
    "```\n",
    "**运行代码**\n",
    "在终端中运行以下命令启动软件公司 ：\n",
    "```python\n",
    "python software_company.py\n",
    "```\n",
    "**运行结果**\n",
    "运行后，终端会打印出以下信息：\n",
    "\n",
    "1.公司投资金额。\n",
    "\n",
    "2.员工的工作状态（例如：Engineer1 is working on the project.）。\n",
    "\n",
    "3.项目完成后的历史记录"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
